package org.convallaria.system.biz.service.impl;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.convallaria.system.biz.service.LoginAttemptService;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.Duration;

/**
 * 登录尝试服务实现
 * 
 * @author convallaria
 * @since 1.0.0
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class LoginAttemptServiceImpl implements LoginAttemptService {

    private final RedisTemplate<String, String> redisTemplate;
    
    private static final String LOGIN_ATTEMPT_PREFIX = "login:attempt:";
    private static final String ACCOUNT_LOCK_PREFIX = "account:lock:";
    private static final int MAX_ATTEMPTS = 5;
    private static final int LOCK_TIME_MINUTES = 30;

    @Override
    public void recordFailedAttempt(String username, String ip) {
        String key = LOGIN_ATTEMPT_PREFIX + username + ":" + ip;
        String attempts = redisTemplate.opsForValue().get(key);
        
        int attemptCount = attempts == null ? 0 : Integer.parseInt(attempts);
        attemptCount++;
        
        if (attemptCount >= MAX_ATTEMPTS) {
            // 锁定账户
            lockAccount(username, ip);
            log.warn("账户 {} 因登录失败次数过多被锁定，IP: {}", username, ip);
        } else {
            // 记录失败次数
            redisTemplate.opsForValue().set(key, String.valueOf(attemptCount), 
                Duration.ofMinutes(LOCK_TIME_MINUTES));
            log.warn("用户 {} 登录失败，IP: {}，失败次数: {}/{}", username, ip, attemptCount, MAX_ATTEMPTS);
        }
    }

    @Override
    public boolean isAccountLocked(String username, String ip) {
        String lockKey = ACCOUNT_LOCK_PREFIX + username + ":" + ip;
        boolean isLocked = redisTemplate.hasKey(lockKey);
        
        if (isLocked) {
            log.warn("账户 {} 被锁定，IP: {}", username, ip);
        }
        
        return isLocked;
    }

    @Override
    public void clearFailedAttempts(String username, String ip) {
        String key = LOGIN_ATTEMPT_PREFIX + username + ":" + ip;
        redisTemplate.delete(key);
        log.info("清除用户 {} 登录失败记录，IP: {}", username, ip);
    }

    /**
     * 锁定账户
     */
    private void lockAccount(String username, String ip) {
        String lockKey = ACCOUNT_LOCK_PREFIX + username + ":" + ip;
        redisTemplate.opsForValue().set(lockKey, "locked", 
            Duration.ofMinutes(LOCK_TIME_MINUTES));
    }
}
